package com.jrx.anytxn.investor.service.impl;

import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanUtils;
import com.jrx.anytxn.investor.bean.InvestorTransferBean;
import com.jrx.anytxn.investor.bean.InvestorTransferSaveBean;
import com.jrx.anytxn.investor.constant.TransBizConstant;
import com.jrx.anytxn.investor.entity.AmLoanAccountInvestorInfo;
import com.jrx.anytxn.investor.entity.AmLoanMainInvestorInfo;
import com.jrx.anytxn.investor.entity.TlGlInterfaceInvestorInfo;
import com.jrx.anytxn.investor.entity.TlInvestorLoanChange;
import com.jrx.anytxn.investor.service.IInvestorGlInterfaceService;
import com.jrx.anytxn.investor.service.IInvestorLoanChangeService;
import com.jrx.anytxn.investor.service.IInvestorTransferTypeStrategy;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.transaction.bean.DelqAccountBean;
import com.jrx.anytxn.transaction.bean.DelqClassifyBean;
import com.jrx.anytxn.transaction.bean.DelqNonAccrualBean;
import com.jrx.anytxn.transaction.bean.DelqParamBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.Date;
import java.util.Optional;

/**
 * 订单账户转列策略
 * 
 * @author liuyang
 * @date 2020-05-27
 **/
@Service
public class InvestorLoanTransferTypeStrategy implements IInvestorTransferTypeStrategy<AmLoanAccountInvestorInfo> {
    
    private static final Logger logger = LoggerFactory.getLogger(IInvestorTransferTypeStrategy.class);

    @Autowired
    private IInvestorGlInterfaceService glInterfaceService;
    @Autowired
    private IInvestorLoanChangeService loanChangeService;

    /**
     * 订单外转列处理 会计状态升级，转表外，五级分类升级
     * 应计非应计转列,订单转列依赖订单逾期天数，是否已转列，但是生成剩余本金gl流水如果依赖于本金转列标志
     *
     * @param transferBean 转列辅助Bean
     * @return InvestorTransferSaveBean 转列保存Bean
     * @throws TxnException
     * @author liuyang
     * @date 2020-05-27
     */
    @Override
    public InvestorTransferSaveBean transferOut(InvestorTransferBean<AmLoanAccountInvestorInfo> transferBean) throws TxnException {
        AmLoanAccountInvestorInfo amLoanAccountInfo = transferBean.getTransferObject();
        logger.info("订单账户外转列amLoanAccountInfo:{}", BeanUtils.toMap(amLoanAccountInfo));
        AmLoanMainInvestorInfo amLoanMainInfo = transferBean.getAmLoanMainInfo();
        DelqParamBean delqParamBean = transferBean.getDelqParamBean();
        Date bussinessDate = transferBean.getBussinessDate();
        int accountingDays = transferBean.getAccountingDays();
        int nonAccrualDays = transferBean.getNonAccrualDays();
        int classifyDays = transferBean.getClassifyDays();
        int delqMaxDays = transferBean.getMaxDelqDays();
        InvestorTransferSaveBean transferSaveBean = new InvestorTransferSaveBean();
        AmLoanAccountInvestorInfo updateLoan = new AmLoanAccountInvestorInfo();
        updateLoan.setId(amLoanAccountInfo.getId());
        updateLoan.setCustomerId(amLoanAccountInfo.getCustomerId());
        updateLoan.setTenantId(amLoanAccountInfo.getTenantId());
        String tempAccountStatus = amLoanAccountInfo.getAccountingPhase();
        boolean isUpdate = false;

        //五级分类
        String classify = delqParamBean.getDelqClassifyBeanList().stream()
                .filter(bean -> classifyDays >= bean.getClassifyDays())
                .map(DelqClassifyBean::getClassifyType)
                .max(String::compareTo)
                .orElse("0");

        //如果与原状态不同则修改
        if (!classify.equals(amLoanAccountInfo.getLoanClassify())) {
            isUpdate = true;
            updateLoan.setLoanClassify(classify);
            amLoanAccountInfo.setLoanClassify(classify);
        }

        //应计/非应计，根据交易账户类型获取对应的参数
        DelqNonAccrualBean delqNonAccrualBean = delqParamBean.getDelqNonAccrualBeanMap().get(TransBizConstant.ACCOUNT_TYPE_05);
        logger.debug("应计/非应计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqNonAccrualBean), amLoanAccountInfo.getNonAccrualsFlag());
        DelqNonAccrualBean prinDelqNonAccrualBean = delqParamBean.getDelqNonAccrualBeanMap().get(TransBizConstant.ACCOUNT_TYPE_06);
        //延滞天数>=转列天数 && 原订单为应计
        if (nonAccrualDays >= delqNonAccrualBean.getTransDays()
                && TransBizConstant.NON_ACCRUALS_FLA_0.equals(amLoanAccountInfo.getNonAccrualsFlag())) {
            isUpdate = true;
            updateLoan.setNonAccrualsFlag(TransBizConstant.NON_ACCRUALS_FLA_1);

            //如果本金允许转列,则将剩余本金转为非应计
            if (TransBizConstant.TRANSFER_FLAG_1.equals(prinDelqNonAccrualBean.getNonAccrualFlag())) {
                String txnCode = delqNonAccrualBean.getNonTxnCode();
                TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(amLoanAccountInfo, amLoanMainInfo, txnCode, tempAccountStatus, bussinessDate, prinDelqNonAccrualBean.getNonAccrualFlag());
                logger.info("应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
                Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

                TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(TransBizConstant.ACCOUNT_TYPE_06,amLoanAccountInfo.getRemainPrincipal().subtract(amLoanAccountInfo.getPrincipalBalance()),TransBizConstant.EVENT_CODE_TN,TransBizConstant.NON_ACCRUALS_FLA_A,TransBizConstant.NON_ACCRUALS_FLA_N);
                transferSaveBean.getLoanChangeList().add(loanChange);
            }

            //整笔转逾期
            if (TransBizConstant.TRANSFER_FLAG_2.equals(prinDelqNonAccrualBean.getNonAccrualFlag())) {
                DelqAccountBean delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                        .filter(bean -> bean.getAccountType().contains(TransBizConstant.ACCOUNT_TYPE_06))
                        .filter(bean -> TransBizConstant.ACCOUNTING_PHASE_1.equals(bean.getAccountingPhase()))
                        .findFirst()
                        .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));
                updateLoan.setAccountingPhase(TransBizConstant.ACCOUNTING_PHASE_1);
                String txnCode = delqAccountBean.getTxnCode();
                String eventCode = delqAccountBean.getEventCode();
                TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(amLoanAccountInfo, amLoanMainInfo, txnCode, tempAccountStatus, bussinessDate, prinDelqNonAccrualBean.getNonAccrualFlag());
                logger.info("整笔转逾期剩余本金转逾期GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
                Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

                TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(TransBizConstant.ACCOUNT_TYPE_06,amLoanAccountInfo.getRemainPrincipal().subtract(amLoanAccountInfo.getPrincipalBalance()),eventCode,TransBizConstant.ACCOUNTING_PHASE_0,TransBizConstant.ACCOUNTING_PHASE_1);
                transferSaveBean.getLoanChangeList().add(loanChange);
            }
        }

        //会计状态转列处理，获取转列天数小于延滞天数，取会计状态最大的那个
        DelqAccountBean delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                .filter(bean -> bean.getAccountType().contains(TransBizConstant.ACCOUNT_TYPE_05))
                .filter(bean -> accountingDays >= bean.getTransferDays())
                .max(Comparator.comparing(DelqAccountBean::getAccountingPhase))
                .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));

        String accountingPhase = delqAccountBean.getAccountingPhase();
        logger.info("会计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqAccountBean), accountingPhase);
        //如果允许转列
        if (!tempAccountStatus.equals(accountingPhase) &&
                TransBizConstant.TRANSFER_METHOD_1.equals(delqNonAccrualBean.getTransferMethod())) {
            isUpdate = true;
            updateLoan.setAccountingPhase(accountingPhase);
            String txnCode = delqAccountBean.getTxnCode();
            String eventCode = delqAccountBean.getEventCode();
            TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(amLoanAccountInfo, amLoanMainInfo, txnCode, tempAccountStatus, bussinessDate, prinDelqNonAccrualBean.getNonAccrualFlag());
            Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

            TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(TransBizConstant.ACCOUNT_TYPE_06,amLoanAccountInfo.getRemainPrincipal().subtract(amLoanAccountInfo.getPrincipalBalance()),eventCode,tempAccountStatus,accountingPhase);
            transferSaveBean.getLoanChangeList().add(loanChange);
        }

        //如果最大延滞天数不同则修改
        if (delqMaxDays != amLoanAccountInfo.getDelqDays()) {
            isUpdate = true;
            updateLoan.setDelqDays(delqMaxDays);
        }

        if (isUpdate) {
            transferSaveBean.setUpdateLoan(updateLoan);
            return transferSaveBean;
        }
        return null;
    }

    /**
     * 订单内转列出处理 会计状态降级，转应计，五级分类降级
     *
     * @param transferBean 转列辅助Bean
     * @return InvestorTransferSaveBean 转列保存Bean
     * @throws TxnException
     * @author liuyang
     * @date 2020-05-27
     */
    @Override
    public InvestorTransferSaveBean transferIn(InvestorTransferBean<AmLoanAccountInvestorInfo> transferBean) throws TxnException {
        AmLoanAccountInvestorInfo amLoanAccountInfo = transferBean.getTransferObject();
        logger.info("订单账户内转列amLoanAccountInfo:{}", BeanUtils.toMap(amLoanAccountInfo));
        AmLoanMainInvestorInfo amLoanMainInfo = transferBean.getAmLoanMainInfo();
        DelqParamBean delqParamBean = transferBean.getDelqParamBean();
        Date bussinessDate = transferBean.getBussinessDate();
        int accountingDays = transferBean.getAccountingDays();
        int nonAccrualDays = transferBean.getNonAccrualDays();
        int classifyDays = transferBean.getClassifyDays();
        int delqMaxDays = transferBean.getMaxDelqDays();
        InvestorTransferSaveBean transferSaveBean = new InvestorTransferSaveBean();
        AmLoanAccountInvestorInfo updateLoan = new AmLoanAccountInvestorInfo();
        updateLoan.setId(amLoanAccountInfo.getId());
        updateLoan.setCustomerId(amLoanAccountInfo.getCustomerId());
        updateLoan.setTenantId(amLoanAccountInfo.getTenantId());
        String tempAccountStatus = amLoanAccountInfo.getAccountingPhase();
        boolean isUpdate = false;

        //五级分类
        String classify = delqParamBean.getDelqClassifyBeanList().stream()
                .filter(bean -> classifyDays >= bean.getClassifyDays())
                .map(DelqClassifyBean::getClassifyType)
                .max(String::compareTo)
                .orElse("0");

        //如果与原状态不同则修改
        if (!classify.equals(amLoanAccountInfo.getLoanClassify())) {
            isUpdate = true;
            updateLoan.setLoanClassify(classify);
            amLoanAccountInfo.setLoanClassify(classify);
        }

        //应计/非应计，根据交易账户类型获取对应的参数
        DelqNonAccrualBean delqNonAccrualBean = delqParamBean.getDelqNonAccrualBeanMap().get(TransBizConstant.ACCOUNT_TYPE_05);
        logger.debug("应计/非应计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqNonAccrualBean), amLoanAccountInfo.getNonAccrualsFlag());
        DelqNonAccrualBean prinDelqNonAccrualBean = delqParamBean.getDelqNonAccrualBeanMap().get(TransBizConstant.ACCOUNT_TYPE_06);
        //延滞天数<转列天数 && 原订单为非应计
        if (nonAccrualDays < delqNonAccrualBean.getTransDays()
                && TransBizConstant.NON_ACCRUALS_FLA_1.equals(amLoanAccountInfo.getNonAccrualsFlag())) {
            isUpdate = true;
            updateLoan.setNonAccrualsFlag(TransBizConstant.NON_ACCRUALS_FLA_0);

            //如果本金允许转列,则将剩余本金转为非应计
            if (TransBizConstant.TRANSFER_FLAG_1.equals(prinDelqNonAccrualBean.getNonAccrualFlag())) {
                String txnCode = delqNonAccrualBean.getInNonTxnCode();
                TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(amLoanAccountInfo, amLoanMainInfo, txnCode, tempAccountStatus, bussinessDate, prinDelqNonAccrualBean.getNonAccrualFlag());
                logger.info("应计/非应计状态转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
                Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

                TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(TransBizConstant.ACCOUNT_TYPE_06,amLoanAccountInfo.getRemainPrincipal().subtract(amLoanAccountInfo.getPrincipalBalance()),TransBizConstant.EVENT_CODE_TA,TransBizConstant.NON_ACCRUALS_FLA_N,TransBizConstant.NON_ACCRUALS_FLA_A);
                transferSaveBean.getLoanChangeList().add(loanChange);
            }

            //整笔转正常
            if (TransBizConstant.TRANSFER_FLAG_2.equals(prinDelqNonAccrualBean.getNonAccrualFlag())) {
                DelqAccountBean delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                        .filter(bean -> bean.getAccountType().contains(TransBizConstant.ACCOUNT_TYPE_06))
                        .filter(bean -> TransBizConstant.ACCOUNTING_PHASE_0.equals(bean.getAccountingPhase()))
                        .findFirst()
                        .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));
                String txnCode = delqAccountBean.getTxnCode();
                String eventCode = delqAccountBean.getEventCode();
                updateLoan.setAccountingPhase(TransBizConstant.ACCOUNTING_PHASE_0);
                amLoanAccountInfo.setNonAccrualsFlag(TransBizConstant.NON_ACCRUALS_FLA_0);
                TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(amLoanAccountInfo, amLoanMainInfo, txnCode, tempAccountStatus, bussinessDate, prinDelqNonAccrualBean.getNonAccrualFlag());
                logger.info("整笔转正常剩余本金转正常转列GL流水为:{}", BeanUtils.toMap(glInterfaceInfo));
                Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

                TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(TransBizConstant.ACCOUNT_TYPE_06,amLoanAccountInfo.getRemainPrincipal().subtract(amLoanAccountInfo.getPrincipalBalance()),eventCode,TransBizConstant.ACCOUNTING_PHASE_1,TransBizConstant.ACCOUNTING_PHASE_0);
                transferSaveBean.getLoanChangeList().add(loanChange);
            }
        }

        //会计状态转列处理，获取转列天数小于延滞天数并且允许转列的参数，取会计状态最大的那个
        DelqAccountBean delqAccountBean = delqParamBean.getDelqAccountBeanList().stream()
                .filter(bean -> bean.getAccountType().contains(TransBizConstant.ACCOUNT_TYPE_05))
                .filter(bean -> accountingDays >= bean.getTransferDays())
                .filter(bean -> TransBizConstant.TRANSFER_FLAG_1.equals(bean.getTransferFlag()))
                .max(Comparator.comparing(DelqAccountBean::getAccountingPhase))
                .orElseThrow(() -> new TxnBizException(ErrorMsgConstant.SYSTEM_PARAMETER_EXISTS));
        String accountingPhase = delqAccountBean.getAccountingPhase();
        logger.info("会计状态转列参数为:{},原状态为:{}", BeanUtils.toMap(delqAccountBean), accountingPhase);
        if (!tempAccountStatus.equals(accountingPhase) &&
                TransBizConstant.TRANSFER_METHOD_1.equals(delqNonAccrualBean.getTransferMethod())) {
            isUpdate = true;
            updateLoan.setAccountingPhase(accountingPhase);
            String txnCode = delqAccountBean.getTxnCode();
            String eventCode = delqAccountBean.getEventCode();
            TlGlInterfaceInvestorInfo glInterfaceInfo = glInterfaceService.buildTlGlInterfaceInvestorInfo(amLoanAccountInfo, amLoanMainInfo, txnCode, tempAccountStatus, bussinessDate, prinDelqNonAccrualBean.getNonAccrualFlag());
            Optional.ofNullable(glInterfaceInfo).ifPresent(gl -> transferSaveBean.getTlGlInterfaceInfoList().add(gl));

            TlInvestorLoanChange loanChange = loanChangeService.genarateLoanChange(TransBizConstant.ACCOUNT_TYPE_06,amLoanAccountInfo.getRemainPrincipal().subtract(amLoanAccountInfo.getPrincipalBalance()),eventCode,tempAccountStatus,accountingPhase);
            transferSaveBean.getLoanChangeList().add(loanChange);
        }

        //如果最大延滞天数不同则修改
        if (delqMaxDays != amLoanAccountInfo.getDelqDays()) {
            isUpdate = true;
            updateLoan.setDelqDays(delqMaxDays);
        }

        if (isUpdate) {
            transferSaveBean.setUpdateLoan(updateLoan);
            return transferSaveBean;
        }
        return null;
    }
}
